/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#pragma once

#include "message_listener.h"
#include "commontypes.h"
#include "event_handlers.h"


enum class PixelType : int
{
    Default = -1,
    Bw = 0,
    Gray = 1,
    Rgb = 2
};

enum class DeviceFeature
{
    Flatbed,
    Feeder,
    Duplex,
};

enum class PaperSource
{
    None = 0,
    Flatbed = 1,
    Feeder = 2,
};

enum class PageSize
{
    Default = -1,
    Auto = 0,
    A4 = 1,
    A5 = 2,
    Letter = 3
};

enum class Orientation : int
{
    Portrait = 0,
    Landscape = 1,
    Rotated90 = 2,
    Rotated180 = 3,
    Rotated270 = 4,
    RotatedAuto = 5
};

typedef struct DeviceInfo
{
    int index; // device index
    wchar_t id[ 64 ]; // device unique identifier ( "{uid}\number" )
    wchar_t uid[ 64 ]; // device model is identifier (can be used in profiles)
    wchar_t manufacturer[ 64 ];
    wchar_t productFamily[ 64 ];
    wchar_t productName[ 64 ];
} DeviceInfo;

class ImagingDevice
{
public:
    ImagingDevice( const DeviceInfo* deviceInfo );
    ~ImagingDevice();
    const DeviceInfo& getDeviceInfo() const;
    void setEventHandler( DisposeEventHandler* eventHandler );

    void* getTag() const;
    void setTag( void* value );

private:
    DisposeEventHandler* m_eventHandler;
    DeviceInfo m_deviceInfo;
    void* m_tag;
};

typedef struct Pixels
{
    uint_t channels;		// number of channels per pixel
    uint_t bitsPerChannel;	// bits per channel
    uint_t bitsPerPixel;	// bits per pixel
    bool paletteInverted;	// indicates whether the palette inverted in the bit map, i.e. black is 0
    long width;				// width in pixels
    long height;			// height in pixels
    long resolution;		// resolution in dpi
    byte_t* pixels;			// array of pixels (byte-aligned)
    uint_t length;			// pixel data length
    uint_t rowStride;		// length in bytes of one image line
    uint_t rowAlignment;	// number of bits the row is aligned by (the standard is 8)
} Pixels;


enum class CapType : int { OneValue, List, Range };
enum class CapValueType : int { Bool, Int, Float, String };

struct BaseCap
{
public:
    uint_t cap;
    CapType type;
    CapValueType valueType;

    BaseCap( uint_t _id, CapType _type, CapValueType _valueType )
        : cap( _id ), type( _type ), valueType( _valueType )
    {
    }

    virtual ~BaseCap() { }
};

template<typename T>
struct ValueCap : public BaseCap
{
    T item;

protected:

    ValueCap( uint_t _id, CapValueType _valueType, T _value )
        : BaseCap( _id, CapType::OneValue, _valueType ),
        item( _value )
    {
    }
};

struct BoolValueCap : public ValueCap<bool>
{
    BoolValueCap( uint_t _id, bool _value ) : ValueCap( _id, CapValueType::Bool, _value ) { }
};

struct IntValueCap : public ValueCap<int>
{
    IntValueCap( uint_t _id, int _value ) : ValueCap( _id, CapValueType::Int, _value ) { }
};

struct FloatValueCap : public ValueCap<float>
{
    FloatValueCap( uint_t _id, float _value ) : ValueCap( _id, CapValueType::Float, _value ) { }
};


template<typename T>
struct RangeCap : public BaseCap
{
    T minValue;
    T maxValue;
    T stepValue;
    T defaultValue;
    T currentValue;

protected:

    RangeCap( uint_t _id, CapValueType _valueType, T _min, T _max, T _step, T _defaultValue, T _currentValue )
        : BaseCap( _id, CapType::Range, _valueType ), minValue( _min ), maxValue( _max ), stepValue( _step ), defaultValue( _defaultValue ), currentValue( _currentValue )
    {
    }
};

struct IntRangeCap : public RangeCap<int>
{
    IntRangeCap( uint_t _id, int _min, int _max, int _step, int _defaultValue, int _currentValue )
        : RangeCap( _id, CapValueType::Int, _min, _max, _step, _defaultValue, _currentValue ) { }
};

struct FloatRangeCap : public RangeCap<float>
{
    FloatRangeCap( uint_t _id, float _min, float _max, float _step, float _defaultValue, float _currentValue )
        : RangeCap( _id, CapValueType::Float, _min, _max, _step, _defaultValue, _currentValue ) { }
};


struct ListBaseCap : public BaseCap
{
    unsigned int count;
    int currentIndex;
    int defaultIndex;

protected:

    ListBaseCap( uint_t _id, CapValueType _valueType, uint_t _count, int _currentIndex, int _defaultIndex )
        : BaseCap( _id, CapType::List, _valueType ),
        count( _count ), currentIndex( _currentIndex ), defaultIndex( _defaultIndex )
    {
    }

    virtual ~ListBaseCap() { }
};

template<typename T>
struct ListCap : ListBaseCap
{
    T* items;

protected:

    ListCap( uint_t _id, CapValueType _valueType, uint_t count, T* _values, int _currentIndex, int _defaultIndex )
        : ListBaseCap( _id, _valueType, count, _currentIndex, _defaultIndex ),
        items( _values )
    {
    }

    virtual ~ListCap()
    {
        delete items;
    }
};

struct BoolListCap : public ListCap<bool>
{
    BoolListCap( uint_t _id, uint_t count, bool* _values, int _currentIndex, int _defaultIndex ) : ListCap( _id, CapValueType::Bool, count, _values, _currentIndex, _defaultIndex ) { }

    BoolListCap( uint_t _id, uint_t count, bool* _values ) : ListCap( _id, CapValueType::Bool, count, _values, -1, -1 ) { }
};

struct IntListCap : public ListCap<int>
{
    IntListCap( uint_t _id, uint_t count, int* _values, int _currentIndex, int _defaultIndex ) : ListCap( _id, CapValueType::Int, count, _values, _currentIndex, _defaultIndex ) { }

    IntListCap( uint_t _id, uint_t count, int* _values ) : ListCap( _id, CapValueType::Int, count, _values, -1, -1 ) { }
};

struct FloatListCap : public ListCap<float>
{
    FloatListCap( uint_t _id, uint_t count, float* _values, int _currentIndex, int _defaultIndex ) : ListCap( _id, CapValueType::Float, count, _values, _currentIndex, _defaultIndex ) { }

    FloatListCap( uint_t _id, uint_t count, float* _values ) : ListCap( _id, CapValueType::Float, count, _values, -1, -1 ) { }
};


class ImageSite;

__interface ImageAcquisitionModel
{
public:

    virtual int getModelTypeId() const = 0;
    virtual char* getModelTypeName() const = 0;
    virtual void setIdentity( char* productName ) = 0;

    virtual bool getDevices() = 0;
    virtual ImagingDevice* getDevice( int index ) = 0;
    virtual int getDeviceCount() = 0;

    virtual bool getShowDeviceUI() const = 0;
    virtual void setShowDeviceUI( bool value ) = 0;

    virtual int getDeviceIndex() const = 0;
    virtual void setDeviceIndex( int value ) = 0;

    virtual const ImagingDevice& getCurrentDevice() const = 0;

    virtual ResultCode scan() = 0;

    virtual PixelType getPixelType() const = 0;
    virtual void setPixelType( PixelType value ) = 0;
    virtual uint_t getResolution() const = 0;
    virtual void setResolution( uint_t value ) = 0;
    virtual PaperSource getPaperSource() const = 0;
    virtual void setPaperSource( PaperSource value ) = 0;
    virtual bool getAutoBright() const = 0;
    virtual void setAutoBright( bool value ) = 0;
    virtual int getContrast() const = 0;
    virtual void setContrast( int value ) = 0;
    virtual double getPageWidth() const = 0;
    virtual void setPageWidth( double value ) = 0;
    virtual double getPageHeight() const = 0;
    virtual void setPageHeight( double value ) = 0;
    virtual void setPageSize( double width, double height ) = 0;

    virtual bool getIsPaperSourceFixed() const = 0;

    virtual bool getDuplex() const = 0;
    virtual void setDuplex( bool value ) = 0;

    virtual int getOrientation() const = 0;
    virtual void setOrientation( int value ) = 0;

    virtual bool getIsDeviceFeatureSupported( DeviceFeature deviceFeature ) const = 0;
    virtual long initializeDevice() = 0;

    virtual void setParentWindow( void* handle ) = 0;

    virtual BaseCap* getCap( uint_t cap ) = 0;

    virtual bool connect() = 0;
    virtual void disconnect() = 0;
    virtual bool getIsConnected() const = 0;

    virtual void deviceChange( bool state ) = 0;

    //virtual ~ImageAcquisitionModel() {}

    //static ImageAcquisitionModel* createInstance( ImageSite* pluginModel, MessageListener* messageListener, int typeId );
};

ImageAcquisitionModel* CreateImageAcquisitionModel( ImageSite* pluginModel, MessageListener* messageListener, int typeId );
